/*
 * Copyright 2016, The Android Open Source Project
 * Copyright (c) 2017-2018 Spotify AB
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.ohos.architecture.blueprints.todoapp.tasks.view;

import ohos.aafwk.ability.AbilitySlice;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.app.Context;

import com.example.ohos.architecture.blueprints.todoapp.tasks.domain.TasksListEvent;
import com.example.ohos.architecture.blueprints.todoapp.tasks.view.TasksListViewData.TaskViewData;
import com.google.common.collect.ImmutableList;
import com.ohos.mobius.ResourceTable;
import com.spotify.mobius.Connectable;
import com.spotify.mobius.Connection;
import com.spotify.mobius.functions.Consumer;

import javax.annotation.Nonnull;

import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;

import static com.example.ohos.architecture.blueprints.todoapp.tasks.domain.TasksListEvent.navigateToTaskDetailsRequested;
import static com.example.ohos.architecture.blueprints.todoapp.tasks.domain.TasksListEvent.newTaskClicked;
import static com.example.ohos.architecture.blueprints.todoapp.tasks.domain.TasksListEvent.taskMarkedActive;
import static com.example.ohos.architecture.blueprints.todoapp.tasks.domain.TasksListEvent.taskMarkedComplete;

/**
 * TasksViews
 */
public class TasksViews implements TasksListViewActions, Connectable<TasksListViewData, TasksListEvent> {
    private final Image mFab;
    private final Observable<TasksListEvent> menuEvents;

    private TasksAdapter mListAdapter;

    private Component mNoTasksView;

    private Image mNoTaskIcon;

    private Text mNoTaskMainView;

    private Text mNoTaskAddView;

    private DirectionalLayout mTasksView;

    private Text mFilteringLabelView;
    private Context context;

    public TasksViews(Context context, AbilitySlice abilitySlice, Image fab,
        Observable<TasksListEvent> menuEvents) {
        this.context = context;
        this.menuEvents = menuEvents;
        mListAdapter = new TasksAdapter();
        // Set up allTasks view
        ListContainer listView = (ListContainer) abilitySlice.findComponentById(ResourceTable.Id_tasks_list);
        listView.setItemProvider(mListAdapter);
        mFilteringLabelView = (Text) abilitySlice.findComponentById(ResourceTable.Id_filteringLabel);
        mTasksView = (DirectionalLayout) abilitySlice.findComponentById(ResourceTable.Id_tasksLL);

        // Set up  no allTasks view
        mNoTasksView = abilitySlice.findComponentById(ResourceTable.Id_noTasks);
        mNoTaskIcon = (Image) abilitySlice.findComponentById(ResourceTable.Id_noTasksIcon);
        mNoTaskMainView = (Text) abilitySlice.findComponentById(ResourceTable.Id_noTasksMain);
        mNoTaskAddView = (Text) abilitySlice.findComponentById(ResourceTable.Id_noTasksAdd);
        mFab = fab;
    }


    @Override
    public void showSuccessfullySavedMessage() {
        showMessage(ResourceTable.String_successfully_saved_task_message);
    }

    @Override
    public void showTaskMarkedComplete() {
        showMessage(ResourceTable.String_task_marked_complete);
    }

    @Override
    public void showTaskMarkedActive() {
        showMessage(ResourceTable.String_task_marked_active);
    }

    @Override
    public void showCompletedTasksCleared() {
        showMessage(ResourceTable.String_completed_tasks_cleared);
    }

    @Override
    public void showLoadingTasksError() {
        showMessage(ResourceTable.String_loading_tasks_error);
    }

    private void showMessage(int messageRes) {
        DirectionalLayout toastLayout = (DirectionalLayout) LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_layout_toast, null, false);
        Text text = (Text) toastLayout.findComponentById(ResourceTable.Id_msg_toast);
        text.setText(context.getString(messageRes));

        ToastDialog toast = new ToastDialog(context);
        toast.setContentCustomComponent(toastLayout);
        toast.setSize(DirectionalLayout.LayoutConfig.MATCH_CONTENT, DirectionalLayout.LayoutConfig.MATCH_CONTENT);
        toast.setAlignment(LayoutAlignment.BOTTOM);
        toast.show();
    }

    @Nonnull
    @Override
    public Connection<TasksListViewData> connect(Consumer<TasksListEvent> output) {
        addUiListeners(output);
        Disposable disposable = menuEvents.subscribe(output::accept);
        return new Connection<TasksListViewData>() {
            @Override
            public void accept(TasksListViewData value) {
                render(value);
            }

            @Override
            public void dispose() {
                disposable.dispose();
                mNoTaskAddView.setClickedListener(null);
                mFab.setClickedListener(null);
                mListAdapter.setItemListener(null);
            }
        };
    }

    private void addUiListeners(Consumer<TasksListEvent> output) {
        mFab.setClickedListener((view) -> {
            output.accept(newTaskClicked());
        });
        mListAdapter.setItemListener(
            new TasksAdapter.TaskItemListener() {
                @Override
                public void onTaskClick(String id) {
                    output.accept(navigateToTaskDetailsRequested(id));
                }

                @Override
                public void onCompleteTaskClick(String id) {
                    output.accept(taskMarkedComplete(id));
                }

                @Override
                public void onActivateTaskClick(String id) {
                    output.accept(taskMarkedActive(id));
                }
            });
    }

    private void showEmptyTaskState(TasksListViewData.EmptyTasksViewData vd) {
        mTasksView.setVisibility(Component.HIDE);
        mNoTasksView.setVisibility(Component.VISIBLE);

        mNoTaskMainView.setText(vd.title());
        mNoTaskIcon.setPixelMap(vd.icon());
        mNoTaskAddView.setVisibility(vd.addViewVisibility());
    }

    private void showNoTasksViewState() {
        mTasksView.setVisibility(Component.HIDE);
        mNoTasksView.setVisibility(Component.HIDE);
    }

    private void showTasks(ImmutableList<TaskViewData> tasks) {
        mListAdapter.replaceData(tasks);

        mTasksView.setVisibility(Component.VISIBLE);
        mNoTasksView.setVisibility(Component.HIDE);
    }

    private void render(TasksListViewData value) {
        mFilteringLabelView.setText(value.filterLabel());
        value
            .viewState()
            .match(
                awaitingTasks -> showNoTasksViewState(),
                emptyTasks -> showEmptyTaskState(emptyTasks.viewData()),
                new com.spotify.dataenum.function.Consumer<ViewState.HasTasks>() {
                    @Override
                    public void accept(ViewState.HasTasks hasTasks) {
                        TasksViews.this.showTasks(hasTasks.taskViewData());
                    }
                });
    }
}
